package me.zhengjie.modules.file.rest;

import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.config.FileProperties;
import me.zhengjie.exception.BizException;
import me.zhengjie.modules.biz.domain.enums.ErrorCode;
import me.zhengjie.modules.file.domain.BizFile;
import me.zhengjie.modules.file.domain.dto.RichTextUploadDto;
import me.zhengjie.modules.file.domain.resp.RichTextUploadResp;
import me.zhengjie.modules.file.service.BizFileService;
import me.zhengjie.modules.file.util.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;

@RestController
@Slf4j
@RequestMapping("/api/file")
@RequiredArgsConstructor
public class FileController{

    private final FileProperties properties;

    @Value(value = "${url.file}")
    private String serverFile;
    @Value(value = "${url.fileUrl}")
    private String fileUrl;

    private final BizFileService bizFileService;


    @PostMapping("/upload")
    @ApiOperation(value = "文件上传")
    @Transactional
    public ResponseEntity<Object> uploadFile(@RequestParam("file") MultipartFile file, Integer category) throws BizException {
        if (file.isEmpty()) {
            throw new BizException(ErrorCode.FILE_NOT_NULL.getCode(), ErrorCode.FILE_NOT_NULL.getMessage());
        }
        // 获取文件名
        String originalFilename = file.getOriginalFilename();

        log.info("/api/file/upload 文件名：{}",originalFilename);

        String fileExtension = "";
        if (originalFilename != null && originalFilename.lastIndexOf(".") != -1) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        }
        // 自定义文件名，确保唯一性
        String fileName = IdUtils.generateRandomId(16) + "." + fileExtension;
        String filePath = serverFile + fileName;
        // 基础目录
        File dest = new File(filePath);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        // 封装文件信息
        BizFile bizFile = new BizFile();
        bizFile.setFileName(originalFilename);
        bizFile.setFileExtension(fileExtension);
        bizFile.setFileSize(file.getSize());
        bizFile.setFilePath(filePath);
        bizFile.setIsDelete(0);
        bizFile.setCreateTime(new Date());
        if (category != null) {
            bizFile.setCategory(category);
        }
        // 保存文件信息到本地服务器
        bizFileService.create(bizFile);

        try {
            file.transferTo(dest);
            return new ResponseEntity<>(fileUrl + fileName, HttpStatus.OK);
        } catch (IOException e) {
            log.error("上传文件失败：{}", e.getMessage());
            throw new BizException(ErrorCode.UPLOAD_FAILED.getCode(), "上传文件失败：" + e.getMessage());
        }
    }

    @PostMapping("/editorUpload")
    @ApiOperation(value = "文件上传")
    @Transactional
    public ResponseEntity<RichTextUploadResp> richTextUpload(@RequestParam("file") MultipartFile file, Integer category) throws BizException {
        if (file.isEmpty()) {
            throw new BizException(ErrorCode.FILE_NOT_NULL.getCode(), ErrorCode.FILE_NOT_NULL.getMessage());
        }
        // 获取文件名
        String originalFilename = file.getOriginalFilename();
        String fileExtension = "";
        if (originalFilename != null && originalFilename.lastIndexOf(".") != -1) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        }
        // 自定义文件名，确保唯一性
        String fileName = IdUtils.generateRandomId(16) + "." + fileExtension;
        String filePath = serverFile +  fileName;
        // 基础目录
        File dest = new File(filePath);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        // 封装文件信息
        BizFile bizFile = new BizFile();
        bizFile.setFileName(originalFilename);
        bizFile.setFileExtension(fileExtension);
        bizFile.setFileSize(file.getSize());
        bizFile.setFilePath(filePath);
        bizFile.setIsDelete(0);
        bizFile.setCreateTime(new Date());
        if (category != null) {
            bizFile.setCategory(category);
        }
        // 保存文件信息到本地服务器
        bizFileService.create(bizFile);

        try {
            file.transferTo(dest);
            RichTextUploadResp resp = new RichTextUploadResp();
            RichTextUploadDto dto = new RichTextUploadDto();
            dto.setUrl(fileUrl+ fileName);
            resp.setErrno(0);
            resp.setData(dto);
            return new ResponseEntity<>(resp, HttpStatus.OK);
        } catch (IOException e) {
            log.error("上传文件失败：{}", e.getMessage());
            RichTextUploadResp resp = new RichTextUploadResp();
            RichTextUploadDto dto = new RichTextUploadDto();
            dto.setUrl(fileUrl + fileName);
            resp.setErrno(1);
            resp.setMessage("文件格式有误或已损坏，请重新上传");
            return new ResponseEntity<>(resp, HttpStatus.OK);
        }
    }

    @GetMapping("/download/{fileName}")
    @ApiOperation(value = "文件下载")
    @Transactional
    public void downloadFile(HttpServletResponse response, @PathVariable String fileName) {
        // 服务器存储文件的路径
        String filePath = serverFile + fileName;

        try {
            File file = new File(filePath);
            if (file.exists()) {
                byte[] content = Files.readAllBytes(file.toPath());
                String encodedFileName = URLEncoder.encode(fileName, String.valueOf(StandardCharsets.UTF_8));

                response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFileName + "\"");
                response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

                // 输出文件内容
                int fileSize = content.length;
                final int maxSize = 100 * 1024;
                int numChunks = (int) Math.ceil((double) fileSize / maxSize);
                byte[] buffer = new byte[maxSize];

                try (InputStream inputStream = new FileInputStream(filePath)) {
                    for (int chunkNumber = 1; chunkNumber <= numChunks; chunkNumber++) {
                        int bytesRead = inputStream.read(buffer);
                        if (bytesRead > 0) {
                            response.getOutputStream().write(buffer, 0, bytesRead);
                        }
                    }
                }
                response.flushBuffer();
            } else {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @DeleteMapping("/delete/{fileName}")
    @ApiOperation(value = "文件删除")
    @Transactional
    public ResponseEntity<Object> deleteFile(@PathVariable String fileName) throws BizException {
        // 获取文件路径
        Path filePath = Paths.get(serverFile + fileName);

        try {
            boolean result = Files.deleteIfExists(filePath);
            if (result) {
                return new ResponseEntity<>("删除成功", HttpStatus.OK);
            } else {
                throw new BizException(ErrorCode.FILE_DELETE_FAILED.getCode(),ErrorCode.FILE_DELETE_FAILED.getMessage());
            }
        } catch (IOException e) {
            log.info("文件删除失败：{}",fileName);
            throw new BizException(ErrorCode.FILE_DELETE_FAILED.getCode(),ErrorCode.FILE_DELETE_FAILED.getMessage());
        }
    }

}